package com.bjsxy.user;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**反射机制*/
public class ReflectTest00 {
    public static void main(String[] args) throws Exception{
        //获取反射对象的三种方法
        //getClass()
        Students students = new Students();
        Class clazz = students.getClass();
        //.Class  静态方法
        Class clazz2 = Students.class;
        //forName()
        Class clazz3 = Class.forName("com.bjsxy.user.Students");

        System.out.println("-------构造方法-----");
        Constructor constructor = clazz.getConstructor(String.class);
        //可以获取private的
        Constructor constructor1 = clazz.getDeclaredConstructor(int.class);
        System.out.println(constructor1);
        //获取public 的公共构造方法
        Constructor[] constructors = clazz.getConstructors();
        //获取所有构造方法
        Constructor[] constructors1 = clazz2.getDeclaredConstructors();
        for(Constructor arr:constructors1){
            System.out.println(arr);
            System.out.println(arr.getName());
        }
        //无参的构造方法
        Constructor constructor2 = clazz.getConstructor(null);

        System.out.println("---通过构造方法创建对象---");
        //先取得构造方法
        Constructor constructor3 = clazz.getConstructor(String.class,int.class);
        //实例化  调用newInstance()方法,写上参数  返回的是Object 类型 的数
        Object ob = constructor3.newInstance("小明",18);
        //强转为原来的类型
        Students s1 = (Students)ob;
        System.out.println(s1.getStudentName()+"\t"+s1.getAge());

        System.out.println();
        System.out.println("获取成员变量");
        //所有 公共public 字段    不可以获取private
        Field[] fields = clazz.getFields();
        //返回Filed类型的一个数组，其中包含Field对象的 所有字段
        Field[] fields1 = clazz2.getDeclaredFields();
        for (Field f:fields1){
            System.out.println(f);
            System.out.println(f.getName());
        }
        //指定的对象
        Field field = clazz3.getDeclaredField("age");
        //返回一个公共 public 字段
        Field field1 = clazz.getField("studentName");
        System.out.println("---通过反射，操作成员变量---");
        //忽略安全检查，可以提高效率  private 可以访问（使用）
        field.setAccessible(true);
        //实例化对象
        Object ob1 = clazz.newInstance();
        //为成员变量赋值   Field类下的 set（Object obj,Object value）
        //obj指的是 对象的引用（指哪个对象），value：赋的值
        field.set(ob1,20);
        field1.set(ob1,"小红");
        //获取成员变量
        Object o1 = field.get(ob1);
        Object o = field1.get(ob1);
        System.out.println(o);
        System.out.println(o1);

        System.out.println();
        System.out.println("---通过反射获取类的方法---");
        //返回一个Method类型的数组，其中包含 所有的方法(本类的方法)
        Method[] methods = clazz.getDeclaredMethods();
        for (Method m:methods){
            System.out.println(m);
            System.out.println(m.getName());
        }
        //返回一个Method类型的数组，其中包含 所有的 公共的public 方法 (Object类的public方法也有)
        Method[] methods1 = clazz.getMethods();
        // 返回一个Method方法对象
        Method method = clazz.getDeclaredMethod("eat");//这是私有方法
        //返回一个(public)公共的Method方法对象
        Method method1 = clazz.getMethod("setAge", int.class);

        System.out.println("---通过反射获取类的使用---");
        //忽略安全检查，可以提高效率  private 可以访问（使用）
        method.setAccessible(true);
        //实例化对象
        Object ob2 = clazz.newInstance();
        //invoke(Object obj,Object... args)
        //obj指的是 对象的引用（指哪个对象） args:可变参数
        method.invoke(ob2);
        System.out.println("-----------------");
        method1.invoke(ob2,22);
        Method method2 = clazz.getMethod("getAge");
        Object o2 = method2.invoke(ob2);
        System.out.println(o2);


    }
}
